package com.lou1052.redis.jedis.api;

import redis.clients.jedis.*;
import redis.clients.util.SafeEncoder;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * redis 给予string 的操作接口
 * String 对象的序列化 和Object 统一
 * Common interface for sharded and non-sharded Jedis
 */
public interface StringCommands extends JedisCommands,BinaryJedisCommands{

  default String set(String key, String value){
    return  set(SafeEncoder.encode(key), SafeEncoder.encode(value));
  }

  default String set(String key, String value, String nxxx, String expx, long time){
    return  set(SafeEncoder.encode(key), SafeEncoder.encode(value), SafeEncoder.encode(nxxx), SafeEncoder.encode(expx), time);
  }

  default String get(String key){
    return SafeEncoder.encode(get(SafeEncoder.encode(key)));
  }

  default Boolean exists(String key){
    return exists(SafeEncoder.encode(key));
  }

  /**
   * 移除给定 key 的生存时间，将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。
   * @param key
   * @return
   * 返回值：
   * 当生存时间移除成功时，返回 1 .
   * 如果 key 不存在或 key 没有设置生存时间，返回 0 。
   */
  default Long persist(String key){
    return persist(SafeEncoder.encode(key));
  }

  /**
   * 返回 key 所储存的值的类型。
   * 返回值：
   * none (key不存在)
   * string (字符串)
   * list (列表)
   * set (集合)
   * zset (有序集)
   * hash (哈希表)
   * @param key
   * @return
   */
  default String type(String key){
    return  type(SafeEncoder.encode(key));
  }

  /**
   * 为给定 key 设置生存时间，当 key 过期时(生存时间为 0 )，它会被自动删除。
   * @param key
   * @param seconds 秒
   * @return
   * 设置成功，返回 1
   * key 不存在或设置失败，返回 0
   */
  default Long expire(String key, int seconds){
    return  expire(SafeEncoder.encode(key),seconds);
  }

  /**
   * 这个命令和 EXPIRE 命令的作用类似，但是它以毫秒为单位设置 key 的生存时间，而不像 EXPIRE 命令那样，以秒为单位。
   * @param key
   * @param milliseconds 毫秒
   * @return
   * 设置成功，返回 1
   * key 不存在或设置失败，返回 0
   */
  default Long pexpire(String key, long milliseconds){
    return pexpire(SafeEncoder.encode(key), milliseconds);
  }

  /**
   * 不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)
   * @param key
   * @param unixTime
   * @return
   * 如果生存时间设置成功，返回 1 。
   * 当 key 不存在或没办法设置生存时间，返回 0 。
   */
  default Long expireAt(String key, long unixTime){
    return expireAt(SafeEncoder.encode(key),unixTime);
  }

  /**
   * 这个命令和 EXPIREAT 命令类似，但它以毫秒为单位设置 key 的过期 unix 时间戳，而不是像 EXPIREAT 那样，以秒为单位。
   * @param key
   * @param millisecondsTimestamp
   * @return
   * 如果生存时间设置成功，返回 1 。
   * 当 key 不存在或没办法设置生存时间时，返回 0 。(查看 EXPIRE 命令获取更多信息)
   */
  default Long pexpireAt(String key, long millisecondsTimestamp){
    return  pexpireAt(SafeEncoder.encode(key),millisecondsTimestamp);
  }

  /**
   * 以秒为单位，返回给定 key 的剩余生存时间(TTL, time to live)。
   * @param key
   * @return
   * 当 key 不存在时，返回 -2 。
   * 当 key 存在但没有设置剩余生存时间时，返回 -1 。
   * 否则，以秒为单位，返回 key 的剩余生存时间。 (在 Redis 2.8 以前，当 key 不存在，或者 key 没有设置剩余生存时间时，命令都返回 -1 。)
   */
  default Long ttl(String key){
    return ttl(SafeEncoder.encode(key));
  }

  /**
   * 对 key 所储存的字符串值，设置或清除指定偏移量上的位(bit)。
   位的设置或清除取决于 value 参数，可以是 0 也可以是 1 。
   当 key 不存在时，自动生成一个新的字符串值。
   字符串会进行伸展(grown)以确保它可以将 value 保存在指定的偏移量上。当字符串值进行伸展时，空白位置以 0 填充。
   offset 参数必须大于或等于 0 ，小于 2^32 (bit 映射被限制在 512 MB 之内)。
   * @param key
   * @param offset
   * @param value
   * @return 指定偏移量原来储存的位。
   */
  default Boolean setbit(String key, long offset, boolean value){
    return  setbit(SafeEncoder.encode(key),offset,value);
  }

  /**
   *
   * @param key
   * @param offset
   * @param value
   * @return
   */
  default Boolean setbit(String key, long offset, String value){
    return  setbit(SafeEncoder.encode(key), offset, SafeEncoder.encode(value));
  }

  /**
   *对 key 所储存的字符串值，获取指定偏移量上的位(bit)
   * @param key
   * @param offset
   * @return 字符串值指定偏移量上的位(bit) 当 offset 比字符串值的长度大，或者 key 不存在时，返回 0
   */
  default Boolean getbit(String key, long offset){
    return getbit(SafeEncoder.encode(key),offset);
  }

  /**
   * 用 value 参数覆写(overwrite)给定 key 所储存的字符串值，从偏移量 offset 开始。
   * 不存在的 key 当作空白字符串处理
   * @param key
   * @param offset
   * @param value
   * @return 被 SETRANGE 修改之后，字符串的长度。
   */
  default Long setrange(String key, long offset, String value){
    return setrange(SafeEncoder.encode(key), offset, SafeEncoder.encode(value));
  }

  /**
   * 返回 key 中字符串值的子字符串，字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。
   * @param key
   * @param startOffset
   * @param endOffset
   * @return 截取得出的子字符串。
   */
  default String getrange(String key, long startOffset, long endOffset){
    return SafeEncoder.encode(getrange(SafeEncoder.encode(key), startOffset, endOffset));
  }

  String getSet(String key, String value);

  Long setnx(String key, String value);

  String setex(String key, int seconds, String value);

  Long decrBy(String key, long integer);

  Long decr(String key);

  Long incrBy(String key, long integer);

  Double incrByFloat(String key, double value);

  Long incr(String key);

  Long append(String key, String value);

  String substr(String key, int start, int end);

  Long hset(String key, String field, String value);

  String hget(String key, String field);

  Long hsetnx(String key, String field, String value);

  String hmset(String key, Map<String, String> hash);

  List<String> hmget(String key, String... fields);

  Long hincrBy(String key, String field, long value);

  Boolean hexists(String key, String field);

  Long hdel(String key, String... field);

  Long hlen(String key);

  Set<String> hkeys(String key);

  List<String> hvals(String key);

  Map<String, String> hgetAll(String key);

  Long rpush(String key, String... string);

  Long lpush(String key, String... string);

  Long llen(String key);

  List<String> lrange(String key, long start, long end);

  String ltrim(String key, long start, long end);

  String lindex(String key, long index);

  String lset(String key, long index, String value);

  Long lrem(String key, long count, String value);

  String lpop(String key);

  String rpop(String key);

  Long sadd(String key, String... member);

  Set<String> smembers(String key);

  Long srem(String key, String... member);

  String spop(String key);

  Set<String> spop(String key, long count);

  Long scard(String key);

  Boolean sismember(String key, String member);

  String srandmember(String key);

  List<String> srandmember(String key, int count);

  Long strlen(String key);

  Long zadd(String key, double score, String member);

  Long zadd(String key, Map<String, Double> scoreMembers);

  Set<String> zrange(String key, long start, long end);

  Long zrem(String key, String... member);

  Double zincrby(String key, double score, String member);

  Long zrank(String key, String member);

  Long zrevrank(String key, String member);

  Set<String> zrevrange(String key, long start, long end);

  Set<Tuple> zrangeWithScores(String key, long start, long end);

  Set<Tuple> zrevrangeWithScores(String key, long start, long end);

  Long zcard(String key);

  Double zscore(String key, String member);

  List<String> sort(String key);

  List<String> sort(String key, SortingParams sortingParameters);

  Long zcount(String key, double min, double max);

  Long zcount(String key, String min, String max);

  Set<String> zrangeByScore(String key, double min, double max);

  Set<String> zrangeByScore(String key, String min, String max);

  Set<String> zrevrangeByScore(String key, double max, double min);

  Set<String> zrangeByScore(String key, double min, double max, int offset, int count);

  Set<String> zrevrangeByScore(String key, String max, String min);

  Set<String> zrangeByScore(String key, String min, String max, int offset, int count);

  Set<String> zrevrangeByScore(String key, double max, double min, int offset, int count);

  Set<Tuple> zrangeByScoreWithScores(String key, double min, double max);

  Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min);

  Set<Tuple> zrangeByScoreWithScores(String key, double min, double max, int offset, int count);

  Set<String> zrevrangeByScore(String key, String max, String min, int offset, int count);

  Set<Tuple> zrangeByScoreWithScores(String key, String min, String max);

  Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min);

  Set<Tuple> zrangeByScoreWithScores(String key, String min, String max, int offset, int count);

  Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count);

  Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count);

  Long zremrangeByRank(String key, long start, long end);

  Long zremrangeByScore(String key, double start, double end);

  Long zremrangeByScore(String key, String start, String end);

  Long zlexcount(final String key, final String min, final String max);

  Set<String> zrangeByLex(final String key, final String min, final String max);

  Set<String> zrangeByLex(final String key, final String min, final String max, final int offset,
                          final int count);

  Set<String> zrevrangeByLex(final String key, final String max, final String min);

  Set<String> zrevrangeByLex(final String key, final String max, final String min,
                             final int offset, final int count);

  Long zremrangeByLex(final String key, final String min, final String max);

  Long linsert(String key, Client.LIST_POSITION where, String pivot, String value);

  Long lpushx(String key, String... string);

  Long rpushx(String key, String... string);

  /**
   * @deprecated unusable command, this will be removed in 3.0.0.
   */
  @Deprecated
  List<String> blpop(String arg);

  List<String> blpop(int timeout, String key);

  /**
   * @deprecated unusable command, this will be removed in 3.0.0.
   */
  @Deprecated
  List<String> brpop(String arg);

  List<String> brpop(int timeout, String key);

  Long del(String key);

  String echo(String string);

  Long move(String key, int dbIndex);

  Long bitcount(final String key);

  Long bitcount(final String key, long start, long end);

  @Deprecated
  /**
   * This method is deprecated due to bug (scan cursor should be unsigned long)
   * And will be removed on next major release
   * @see https://github.com/xetorthio/jedis/issues/531 
   */
  ScanResult<Map.Entry<String, String>> hscan(final String key, int cursor);

  @Deprecated
  /**
   * This method is deprecated due to bug (scan cursor should be unsigned long)
   * And will be removed on next major release
   * @see https://github.com/xetorthio/jedis/issues/531 
   */
  ScanResult<String> sscan(final String key, int cursor);

  @Deprecated
  /**
   * This method is deprecated due to bug (scan cursor should be unsigned long)
   * And will be removed on next major release
   * @see https://github.com/xetorthio/jedis/issues/531 
   */
  ScanResult<Tuple> zscan(final String key, int cursor);

  ScanResult<Map.Entry<String, String>> hscan(final String key, final String cursor);

  ScanResult<String> sscan(final String key, final String cursor);

  ScanResult<Tuple> zscan(final String key, final String cursor);

  Long pfadd(final String key, final String... elements);

  long pfcount(final String key);

}
